package com.xxl.job.executor.service.jobhandler;

import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import org.springframework.stereotype.Component;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.file.Paths;

@Component
public class WindowsExeJob {

    /**
     * Windows 可执行程序/命令行任务处理器
     * 用于执行外部EXE程序或CMD命令
     */
    @XxlJob("exe")
    public void winExeJobHandler() {
        // 获取任务参数（可执行文件路径）
        String exePath = XxlJobHelper.getJobParam();
        Process process = null;

        try {
            // 验证参数有效性
            if (exePath == null || exePath.trim().isEmpty()) {
                XxlJobHelper.log("错误：未指定可执行文件路径");
                return;
            }

            // 创建进程构建器
            ProcessBuilder processBuilder = new ProcessBuilder(exePath);
            // 设置工作目录为可执行文件所在目录
            processBuilder.directory(Paths.get(exePath).getParent().toFile());

            // 启动进程
            process = processBuilder.start();

            // 启动线程处理标准输出
            Thread outputThread = createOutputHandlingThread(process.getInputStream(), false);
            // 启动线程处理错误输出
            Thread errorThread = createOutputHandlingThread(process.getErrorStream(), true);

            outputThread.start();
            errorThread.start();

            // 等待进程执行完成
            int exitCode = process.waitFor();

            // 等待输出处理线程完成
            outputThread.join();
            errorThread.join();

            // 记录命令执行结果
            XxlJobHelper.log("命令执行完成，返回码: " + exitCode);

        } catch (IOException e) {
            XxlJobHelper.log("执行命令时发生I/O错误: " + e.getMessage());
        } catch (InterruptedException e) {
            XxlJobHelper.log("命令执行被中断: " + e.getMessage());
            // 恢复中断状态
            Thread.currentThread().interrupt();
        } finally {
            // 确保进程被销毁
            if (process != null) {
                process.destroy();
            }
        }
    }

    /**
     * 创建用于处理进程输出流的线程
     *
     * @param inputStream   要处理的输入流
     * @param isErrorStream 是否为错误流
     * @return 处理线程
     */
    private Thread createOutputHandlingThread(InputStream inputStream, boolean isErrorStream) {
        return new Thread(() -> {
            try (BufferedReader reader = new BufferedReader(
                    new InputStreamReader(inputStream, "GBK"))) {

                String line;
                while ((line = reader.readLine()) != null) {
                    if (isErrorStream) {
                        XxlJobHelper.log("错误: " + line);
                    } else {
                        XxlJobHelper.log(line);
                    }
                }

            } catch (IOException e) {
                String streamType = isErrorStream ? "错误" : "标准";
                XxlJobHelper.log("读取" + streamType + "输出失败: " + e.getMessage());
            }
        });
    }
}
